package dk.simonvogensen.itodo.server;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import dk.simonvogensen.itodo.server.dao.ConfigDAO;
import dk.simonvogensen.itodo.server.dao.PersistedTodoItemDAO;
import dk.simonvogensen.itodo.server.model.PersistedTodoItem;
import dk.simonvogensen.itodo.shared.model.Config;
import dk.simonvogensen.itodo.shared.model.TodoItem;

import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: simon
 * Date: Oct 23, 2009
 * Time: 8:00:47 PM
 * To change this template use File | Settings | File Templates.
 */
public class TodoService {
    
    private final PersistenceManagerFactory pmf;

    private PersistedTodoItemDAO persistedTodoItemDAO = new PersistedTodoItemDAO();
    private ConfigDAO configDAO = new ConfigDAO();

    private User user; // set every request

    public TodoService(PersistenceManagerFactory pmf) {
        this.pmf = pmf;
    }

    public List<TodoItem> getTodoItemList(int startIndex, int endIndex) {
        if (hasUser()) {
            PersistenceManager pm = pmf.getPersistenceManager();
            Config config = configDAO.get(user.getEmail(), pm);
            if (config == null) {
                config = new Config("home=0;office=30", "project1;project2");
                configDAO.create(config, pm);
            }

            List<PersistedTodoItem> persistedTodoItems = persistedTodoItemDAO.listByEmail(user.getEmail(), startIndex, endIndex, pm);
//            List<PersistedTodoItem> detachedTodoItems = (List<PersistedTodoItem>) pm.detachCopyAll(persistedTodoItems);
            List<TodoItem> list = initTodoItemList(config, persistedTodoItems);
            pm.close();
            return list;
        } else {
            return null;
        }
    }

    protected static List<TodoItem> initTodoItemList(Config config, List<PersistedTodoItem> persistedTodoItemList) {
        //parse, sort and link items
        Collections.sort(persistedTodoItemList, new Comparator() {
            public int compare(Object o1, Object o2) {
                return ((PersistedTodoItem) o2).getIndex() - ((PersistedTodoItem) o1).getIndex();
            }
        });
        TodoItem prevItem = null;
        List<TodoItem> todoItemList = new ArrayList<TodoItem>();
        for (int i = persistedTodoItemList.size() - 1; i >= 0; i--) {
            PersistedTodoItem persistedTodoItem = persistedTodoItemList.get(i);
            TodoItem item = persistedTodoItem.createTodoItem(config);
            item.setConfig(config);
            item.setPrevItem(prevItem);
            todoItemList.add(0, item);
            prevItem = item;
        }
        return todoItemList;
    }

    public void deleteTodo(TodoItem todoItem) {
        if (hasUser()) {
            PersistenceManager pm = pmf.getPersistenceManager();
            persistedTodoItemDAO.delete(todoItem.getId(), user.getEmail(), pm);
            pm.close();
        }
    }

    public String createTodo() {
        if (hasUser()) {
            PersistenceManager pm = pmf.getPersistenceManager();
            TodoItem todoItem = new TodoItem();
            todoItem.setEmail(user.getEmail());
            String id = persistedTodoItemDAO.create(todoItem, pm);
            pm.close();
            return id;
        } else
            return null;
    }

    public void updateTodo(TodoItem todoItem) {
        if (hasUser()) {
            PersistenceManager pm = pmf.getPersistenceManager();
            todoItem.setEmail(user.getEmail());
            persistedTodoItemDAO.update(todoItem, pm);
            pm.close();
        }
    }

    public String updateConfig(Config config) {
        if (hasUser()) {
            PersistenceManager pm = pmf.getPersistenceManager();
            config.setEmail(user.getEmail());
            return configDAO.update(config, pm);
        } else {
            return null;
        }
    }

    public boolean hasUser() {
        user = getUser();
        return user != null;
    }

    private User getUser() {
        UserService userService = UserServiceFactory.getUserService();
        return userService.getCurrentUser();
    }

    public TodoItem getLatestTodoItem() {
        if (hasUser()) {
            PersistenceManager pm = pmf.getPersistenceManager();
            Config config = configDAO.get(user.getEmail(), pm);

            if (config == null) {
                config = new Config("home=0;office=30", "project1;project2");
                config.setEmail(user.getEmail());
                configDAO.create(config, pm);
            }

            PersistedTodoItem persistedTodoItem = persistedTodoItemDAO.getByLatest(user.getEmail(), pm);

            TodoItem todoItem;
            if(persistedTodoItem == null) {
                String id = persistedTodoItemDAO.create(new TodoItem(), pm);
                todoItem = new TodoItem(config, id, null, 0);
            } else {
                todoItem = persistedTodoItem.createTodoItem(config);
            }

            pm.close();
            return todoItem;
        } else {
            return null;
        }
    }

    public TodoItem getTodoItem(int index) {
        if (hasUser()) {
            PersistenceManager pm = pmf.getPersistenceManager();
            Config config = configDAO.get(user.getEmail(), pm);
            PersistedTodoItem persistedTodoItem = persistedTodoItemDAO.getByIndex(user.getEmail(), index, pm);
            if(persistedTodoItem == null) return null;
            TodoItem todoItem = persistedTodoItem.createTodoItem(config);
            pm.close();
            return todoItem;
        } else {
            return null;
        }
    }

    public void importData(String importString) {
        if (hasUser()) {
            PersistenceManager pm = pmf.getPersistenceManager();
//            Config config = configDAO.get(user.getEmail(), pm);
//
//            configDAO.update(config, pm);

            List<TodoItem> todoItems = importData(importString, user.getEmail());
            for (TodoItem todoItem : todoItems) {
                persistedTodoItemDAO.create(todoItem, pm);
            }

            pm.close();
        }
    }

    public static List<TodoItem> importData(String importString, String email) {
        List<TodoItem> result = new ArrayList<TodoItem>();
        String[] itodoArray = importString.split("<todoitem>");
        for (int i = 1; i < itodoArray.length; i++) {
            TodoItem todoItem = new TodoItem(null, i-1, itodoArray[i].replace("</todoitem>\n", ""));
            todoItem.setEmail(email);
            result.add(todoItem);
        }
        Collections.reverse(result);
        return result;
    }
}

